// SUGARSCAPE MODEL FOR SWARM
// Based on Nelson Minar's 1996-1997 model; modified by 
// Andre Manoel (andremanoel@gmail.com) with research  
// purposes. See file README for more information.

// The SugarSpace is the object that represents the environment of the model
// Its main component is the amount of sugar in the world
// It also enforces dynamics on the sugar space (growing new sugar) and
//   keeps track of where all the agents are

#import <objectbase/SwarmObject.h>
#import <space.h>

@class SugarAgent;

// A SugarValue is a measurement of how much sugar is at the world.
// We define a new type here, but it's basically just a real number
typedef float SugarValue;
typedef float SpiceValue;

// Here is the SugarSpace object itself. It inherits very little behaviour,
//   but contains various objects to store properties of the world
@interface SugarSpace: SwarmObject
{
  unsigned int xsize, ysize;				  // grid size
  
  int activSpice;				  // activate spice
  id <Discrete2d> sugar, spice, values;		  // goods at each spot
  id <Discrete2d> pollution;			  // pollution at each spot
  int sugarGrowRate;				  // alpha, from the book
  int spiceGrowRate;                              // analogous to alpha  

  int time;					  // variable for time count
  int winterDuration, winterGrowRate;		  // seasonal growback pmts.
  float pollutionS, pollutionM;			  // pollution parameters
  int turnsToDiffuse;				  // turns to diffuse pollut.
  int polStart, polEnd, diffStart;		  // when pollut. starts
  int plagueEach, plagueFor;			  // plague parameters

  const char *maxSugarDataFile;			  // filename for max sugar
  id <Discrete2d> maxSugar;			  // max sugar at each spot
  SugarValue globalMaxSugar;			  // sugar absolute maximum
  const char *maxSpiceDataFile;			  // filename for max spice
  id <Discrete2d> maxSpice;			  // max spice at each spot
  SpiceValue globalMaxSpice; 			  // spice absolute maximum
 
  id <Grid2d> agentGrid;			  // agent positions
}

// Use this method at object creation - set the size of the world
- setSizeX: (int)x Y: (int)y;
- (int)getSizeX;
- (int)getSizeY;
// Also set the maximum sugar datafile
- setMaxSugarDataFile: (const char *)s;
- setMaxSpiceDataFile: (const char *)s;

// Dynamics; add more sugar and spice to the world.
- updateSugar;
- setSugarGrowRate: (int)a;
- setSeasonsOf: (int)t WithGrowRate: (float)g;
- (int)getSugarGrowRate;
- setSpiceGrowRate: (int)a;
- (int)getSpiceGrowRate;

// Methods for managing the time counter
- setTime: (int)t;
- (int)getTime;
- updateTime;

// Manage pollution on the Sugarscape
- setPollutionS: (float)s M: (float)m diffEach: (int)turns;
- setPollutStart: (int)ps pollutEnd: (int)pe diffStart: (int)ds;
- (float)getPollutAtX: (int)x Y: (int)y;
- addPollutionForS: (float)s forM: (float)m atX: (int)x Y: (int)y;
- diffusePollution;

// Manage plague on the Sugarscape
- setPlagueEach: (int)e forLongAs: (int)f;

// This code handles the main property of a SugarSpace: how much sugar
//   and spice there is at each spot in the world, and taking that sugar
//   and spice
- (SugarValue)getSugarAtX: (int)x Y: (int)y;
- (SugarValue)takeSugarAtX: (int)x Y: (int)y; // take all
- (SugarValue)takeSugar: (float)s AtX: (int)x Y: (int)y;
- (SpiceValue)getSpiceAtX: (int)x Y: (int)y;
- (SpiceValue)takeSpiceAtX: (int)x Y: (int)y; // take all
- (SpiceValue)takeSpice: (float)s AtX: (int)x Y: (int)y;
- (id <Discrete2d>)getValues;
- updateValues;

// Read out the maximum value of sugar and spice from the space
- (SugarValue)getGlobalMaxSugar;
- (SpiceValue)getGlobalMaxSpice;

// This code handles the position of all the agents in the sugarspace.
// Look for agents in the space, add, move, and remove them
- (SugarAgent *)getAgentAtX: (int)x Y: (int)y;
- addAgent: (SugarAgent *)agent atX: (int)x Y: (int)y;
- removeAgent: (SugarAgent *)agent;
- moveAgent: (SugarAgent *)agent toX: (int)x Y: (int)y;

// Get the array of all the agents in the space
- (id <Grid2d>)getAgentGrid;

// Coordinate normalization. This handles coordinates out of range by
//   wrapping them around
- (int)xnorm: (int)x;
- (int)ynorm: (int)y;

@end
